//
//  XIScene.m
//  XI Engine
//
//  Created by Balazs Faludi on 25.05.09.
//  Copyright 2009 Balazs Faludi. All rights reserved.
//

#import <objc/runtime.h>
#import "XIEngine.h"

@implementation XIScene

@synthesize ignoresPause;
//@synthesize backgroundColor;
@synthesize mainLayer, layers;

#pragma mark -
#pragma mark Constuctor & desctructor

- (id)init {
    if ((self = [super init])) {
		ignoresPause = NO;
		//backgroundColor = [XIColor blueColor];
		NSArray *myLayers = [[NSArray alloc] init];
		self.layers = myLayers;
		[myLayers release];
    }
    return self;
}

- (id)initFromDictionary:(NSDictionary *)dict
{
	if ((self = [self init])) {
		@try {
			// If the file contains properties of the scene, fo through them and set the scene properties.
			// If the property does not exist, try sending it as a message.
			NSDictionary *properties = [dict objectForKey:@"properties"];
			if(properties)
			{
				NSEnumerator *enumerator = [properties keyEnumerator];
				NSString *propertyName;
				while ((propertyName = [enumerator nextObject])) {
					if(!setValueOfObjectForPropertyName(&self, propertyName, [properties valueForKey:propertyName]))
					{performSelectorOfObject(&self, propertyName, [properties valueForKey:propertyName]);}
				}
			}
			
			// If the file contains objects, init them and add to the scene.
			NSArray *myLayers = [dict objectForKey:@"layers"];
			if(myLayers)
			{
				for(NSDictionary *layerDict in myLayers)
				{
				//	XILayer *layer = [[XILayer alloc] initFromDictionary:layerDict];
					NSString *class = [layerDict valueForKey:@"class"];
					if(!class || [class isEqualToString:@""]){class = @"XILayer";}
					id layer = [newObjectWithClassName(class) init];
					[self addLayer:layer];
					[layer loadFromDictionary:layerDict];
					[layer release];
				}
			}
		}
		@catch (NSException * e) {
			[NSException raise:@"XILoadingException" format:@"Scene cannot be loaded from specified dictionary"];
			return nil;
		}
	}
	return self;
}

- (id)initWithXilName:(NSString *)xilName bundle:(NSBundle *)xilBundle {
	if ((self = [self init])) {
		
		@try {
			// Load the xil file.
			NSString *path = [xilBundle pathForResource:xilName ofType:@"xil"];
			NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
			return [self initFromDictionary:dict];
			
		}
		@catch (NSException * e) {
			[NSException raise:@"XILoadingException" format:@"Xil file \"%@.xil\" not found in bundle's ressource path at \"%@\".",
			 xilName, [xilBundle resourcePath]];
			return nil;
		}
	}
    return self;
}

- (NSMutableDictionary *)saveStateToDictionary
{
	NSMutableArray *layersArray = [NSMutableArray arrayWithCapacity:30];
	for(XILayer *l in layers)
	{
		NSDictionary *layerDict = [l saveToDictionary];
		[layersArray addObject:layerDict];
	}
	return [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:ignoresPause], @"ignoresPause",
			layersArray, @"objects", nil];
}

- (NSDictionary *)saveToDictionary
{
	NSMutableDictionary *mutable = [NSMutableDictionary dictionaryWithCapacity:2];
	[mutable setObject:[self className] forKey:@"class"];
	[mutable setObject:[self saveStateToDictionary] forKey:@"properties"];
	return mutable;	
}

- (void)dealloc {
    [layers release];
	[mainLayer release];
    [super dealloc];
}

#pragma mark -
#pragma mark Layer manipulation

// Add an layer to the top of the layer array. Layers that are added later will appear on top of others.
- (void)addLayer:(XILayer *)layer
{
	NSMutableArray *mutable = [[NSMutableArray alloc] initWithArray:layers];
	[mutable addObject:layer];
	self.layers = mutable;
	[mutable release];
	layer.scene = self;
}

- (void)insertLayer:(XILayer *)layer atIndex:(int)index
{
	NSMutableArray *mutable = [NSMutableArray arrayWithArray:layers];
	[mutable insertObject:layer atIndex:index];
	self.layers = mutable;
	layer.scene = self;
}

- (void)removeLayer:(XILayer *)layer
{
	layer.scene = nil;
	NSMutableArray *mutable = [NSMutableArray arrayWithArray:layers];
	for(int i = 0; i < [mutable count]; i++)
	{
		if([mutable objectAtIndex:i] == layer)
		{
			[mutable removeObjectAtIndex:i];
		}
	}
	self.layers = mutable;
}



#pragma mark -
#pragma mark Loop

#if TARGET_OS_IPHONE
- (void)update
{	
	// Return from function, if game is paused and scene doesn't ignore pause.
	if(!ignoresPause && [XIGame sharedGame].paused){return;}
	
	// Go though all the objects and send an update message to them.
	// Each object it responsible to update itself (position, angle, whatever) by implementing the update method.
	for(XILayer *layer in layers)
	{
		[layer update];
	}
}
#endif

- (void)draw
{
	// Go through all the objects and send a draw message to them.
	// Each object is responsive to draw itself by implementing the draw method.
	
	for(XILayer *layer in layers)
	{
		[layer draw];
	}
}

#pragma mark -
#pragma mark Abstract

- (void)willBecomeActiveScene{}
- (void)didBecomeActiveScene{}
- (void)willResignActiveScene{}
- (void)didResignActiveScene{}
#if TARGET_OS_IPHONE
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration{}
#endif



@end
